package cn.sxw.ld.module.setmeal.service.impl;

import cn.sxw.ld.module.setmeal.dto.SetmealDto;
import cn.sxw.ld.common.exception.CustomException;
import cn.sxw.ld.module.setmeal.mapper.SetmealMapper;
import cn.sxw.ld.module.category.pojo.Category;
import cn.sxw.ld.module.setmeal.pojo.Setmeal;
import cn.sxw.ld.module.setmeal.pojo.SetmealDish;
import cn.sxw.ld.module.category.service.CategoryService;
import cn.sxw.ld.module.setmeal.service.SetmealDishService;
import cn.sxw.ld.module.setmeal.service.SetmealService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;
import java.util.stream.Collectors;

/**
 * ClassName:SetmealServiceImpl
 * Package:cn.sjxy.graduation.service.impl
 * Description:
 *
 * @Date:2022/5/27 20:52
 * @Author:SXW
 */
@Service
public class SetmealServiceImpl extends ServiceImpl<SetmealMapper, Setmeal> implements SetmealService {

    @Autowired
    private SetmealDishService setmealDishService;

    @Lazy
    @Autowired
    private CategoryService categoryService;

    @Transactional // 保证两表事务一致性
    public void saveDishAndSetmealDish(SetmealDto setmealDto) {
        // 1. Dish 表，保存菜品基本信息
        this.save(setmealDto);
        List<SetmealDish> setmealDishes = setmealDto.getSetmealDishes();
        setmealDishes.stream().map((item) -> {
            item.setSetmealId(setmealDto.getId());
            return item;
        }).collect(Collectors.toList());

        // 2. setmeal_dish 表，保存套餐与菜品关联关系
        setmealDishService.saveBatch(setmealDishes);
    }

    /**
     * 需求：
     * 1. 停售的套餐才可删除
     * 2. 删除两张表中对应信息
     *
     * @param ids
     */
    @Transactional
    @Override
    public void deleteDishAndSetmealDish(List<Long> ids) {
        // 查询套餐状态
        LambdaQueryWrapper<Setmeal> setmealWrapper = new LambdaQueryWrapper<>();
        setmealWrapper.in(Setmeal::getId, ids);
        setmealWrapper.eq(Setmeal::getStatus, 1);
        Long count = this.count(setmealWrapper);
        if (count > 0) {
            throw new CustomException("该套餐售卖中，删除失败！");
        }

        // 若可以删除，先删除 Setmeal 表中数据
        this.removeByIds(ids);

        // 在删除关联表中数据
        LambdaQueryWrapper<SetmealDish> setmealDishWrapper = new LambdaQueryWrapper<>();
        setmealDishWrapper.in(SetmealDish::getSetmealId, ids);
        setmealDishService.remove(setmealDishWrapper);
    }

    @Override
    public void changeStatus(List<Long> ids, Integer status) {
        List<Setmeal> setmeals = this.listByIds(ids);
        // 使用流方式读取集合中数据并修改
        setmeals.stream().map((item) -> { // 一个 item 即表示一个 Setmeal
            item.setStatus(status); // 将查询到的数据做修改
            this.updateById(item); // 将修改数据存回数据库
            return item;
        }).collect(Collectors.toList());
    }

    @Override
    public Page getPage(int page, int pageSize, String name) {
        // 分页构造器
        Page<Setmeal> pageInfo = new Page<>(page, pageSize);
        Page<SetmealDto> setmealDtoPage = new Page<>();

        // 条件构造器，添加排序条件
        LambdaQueryWrapper<Setmeal> wrapper = new LambdaQueryWrapper<>();
        wrapper.like(name != null, Setmeal::getName, name);
        wrapper.orderByDesc(Setmeal::getUpdateTime);

        this.page(pageInfo, wrapper);

        // 因为页面需要的是名称，而不是编号，故需转换
        BeanUtils.copyProperties(pageInfo, setmealDtoPage, "records");

        // 处理 records
        List<Setmeal> records = pageInfo.getRecords();
        List<SetmealDto> setmealDtos = records.stream().map((item) -> {
            SetmealDto setmealDto = new SetmealDto();

            Long categoryId = item.getCategoryId();
            Category category = categoryService.getById(categoryId);
            if (category != null) {
                String categoryName = category.getName();
                setmealDto.setCategoryName(categoryName);
                // item 代表一个 setmealDto 对象，但对象中只设置了 categoryName 的值，其他值均为空。故将其他值拷贝到 item 中
                BeanUtils.copyProperties(item, setmealDto);
            }
            return setmealDto;
        }).collect(Collectors.toList());

        setmealDtoPage.setRecords(setmealDtos);
        return setmealDtoPage;
    }

    /**
     * 查询套餐信息
     *
     * @param setmeal
     * @return
     */
    @Override
    public List<Setmeal> getSetmeals(Setmeal setmeal) {
        LambdaQueryWrapper<Setmeal> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
        setmealLambdaQueryWrapper.eq(setmeal.getCategoryId() != null, Setmeal::getCategoryId, setmeal.getCategoryId());
        setmealLambdaQueryWrapper.eq(setmeal.getStatus() != null, Setmeal::getStatus, setmeal.getStatus());
        setmealLambdaQueryWrapper.orderByDesc(Setmeal::getUpdateTime);
        List<Setmeal> list = this.list(setmealLambdaQueryWrapper);
        return list;
    }

    /**
     * 回显数据
     *
     * @param id
     * @return
     */
    @Override
    public SetmealDto viewBack(Long id) {

        Setmeal setmeal = this.getById(id);

        // 接收分类信息
        SetmealDto setmealDto = new SetmealDto();

        // SetmealDto 类中也具有 Setmeal 的相关信息，将查询到的基本信息拷贝给转换类
        BeanUtils.copyProperties(setmeal, setmealDto);

        LambdaQueryWrapper<SetmealDish> setmealLambdaQueryWrapper = new LambdaQueryWrapper<>();
        setmealLambdaQueryWrapper.eq(SetmealDish::getSetmealId, id);
        List<SetmealDish> setmealDishes = setmealDishService.list(setmealLambdaQueryWrapper);
        setmealDto.setSetmealDishes(setmealDishes);
        return setmealDto;
    }


}

